/**
 * @file:          CommunicationInterface.h
 * @brief:
 * @details:
 * @author:        wjh
 * @date created:  2023.06.19
 * @version:       1.0.0
 * @par copyright (c):
 *
 * @par history (desc):
 *   version:1.0.0, wjh, 2023.06.19,13:46:08
 */

#ifndef _COMMUNICATIONINTERFACE_H_
#define _COMMUNICATIONINTERFACE_H_

/* Include Files **************************************************************/
#include "Datatype.h"
#include "common.h"

/* Macro Definition ***********************************************************/
/* cmd system version */
#define CMD_SYSTEM_VERSION_MAJOR ((uint8_t)1)
#define CMD_SYSTEM_VERSION_MINOR ((uint8_t)2)
#define CMD_SYSTEM_RELEASE_DATE ("2024-03-21 15:47:21")

#define TERMINAL(...) printf(__VA_ARGS__)
#define TERMINAL_Adv(...) DBprintfDMAAdv_Add(__VA_ARGS__)
#define TERMINAL_AdvStr(...) DBprintfDMAAdv_AddStr(__VA_ARGS__)
#define TERMINAL_AdvStr_N(str, n) DBprintfDMAAdv_AddStr_N(str, n)
#define COMMAND_MAX_NUM 5
#define COMMAND_MAX_STRLEN 50
#define SNED_DATA_ARRAY_MAX_SIZE 30

/* Data Type Define ***********************************************************/
enum BroadcastSupport
{
    BroadcastSupport_No = 0,
    BroadcastSupport_Yes = 1,
};

enum DataPackInType
{
    DATA_PACK_IN_TYPE_CMD = 0,
    DATA_PACK_IN_TYPE_MOTION_CMD = 1,
    VALID_NUM_OF_DATA_PACK_IN_TYPE_MOTION_CMD = 2,
};

enum Command
{
    COMMAND_HELP = 0,
    COMMAND_CONFIG = 1,
    VALID_NUM_OF_COMMAND = 2,
};

enum DataPackOutType
{
    DATA_OUT_TYPE_PROTECTION = 0,
    DATA_OUT_TYPE_LOG = 0,
    DATA_OUT_TYPE_CMD = 0,
    DATA_OUT_TYPE_CONFIG = 0
};

typedef struct DataRaw
{
    uint16 data_len;
    uint8 parity;
    uint8 pack_type;
    uint8 *databyte;
} DataRaw;

enum DataFrameFormat_Enum
{
    DataFrameFormat_Head = 0,
    DataFrameFormat_Addr,
    DataFrameFormat_DataLength,
    DataFrameFormat_Status,
    DataFrameFormat_FunctionCode,
    DataFrameFormat_Data,
    DataFrameFormat_Parity,
    DataFrameFormat_End
};

enum DataFrame_Enum
{
    DataFrame_Head = 0xF7,
};

enum SlaveAddr_Enum
{
    SlaveAddr_Broadcast = 0xFF,
    SlaveAddr_Invalid = 0x80,
    SlaveAddr_Base = 0x81,
    SlaveAddr_1 = 0x81,
    SlaveAddr_2 = 0x82,
    SlaveAddr_3 = 0x83,
    SlaveAddr_4 = 0x84,
    SlaveAddr_5 = 0x85,
    SlaveAddr_6 = 0x86,
    SlaveAddr_7 = 0x87,
    SlaveAddr_8 = 0x88,
};

enum FunctionCmdCode1st_Enum
{
    FunctionCmdCode1st_help = 0,
    FunctionCmdCode1st_reboot,
    FunctionCmdCode1st_encoder_calibrate,
    FunctionCmdCode1st_encoder_calibrate_official,
    FunctionCmdCode1st_elec_offset_calibrate,
    FunctionCmdCode1st_control,
    FunctionCmdCode1st_sys_param,
    FunctionCmdCode1st_flash_param,
    FunctionCmdCode1st_get,
    FunctionCmdCode1st_logger,
    FunctionCmdCode1st_ripple_cal,
    FunctionCmdCode1st_boot,
    FunctionCmdCode1st_protection,
    FunctionCmdCode1st_SystemId_RL,
    FunctionCmdCode1st_rs485_addr,
    FunctionCmdCode1st_version,
    FunctionCmdCode1st_control_loop,
    FunctionCmdCode1st_emergency_pin_mode,
    FunctionCmdCode1st_data_sampler,
    FunctionCmdCode1st_trajectory_plan,
    FunctionCmdCode1st_end,

};

enum FunctionCmdCode2st_help_Enum
{
    FunctionCmdCode2st_help = 0,
    FunctionCmdCode2st_help_reboot,
    FunctionCmdCode2st_help_encoder_calibrate,
    FunctionCmdCode2st_help_encoder_calibrate_official,
    FunctionCmdCode2st_help_elec_offset_calibrate,
    FunctionCmdCode2st_help_control,
    FunctionCmdCode2st_help_sys_param,
    FunctionCmdCode2st_help_flash_param,
    FunctionCmdCode2st_help_get,
    FunctionCmdCode2st_help_logger,
    FunctionCmdCode2st_help_ripple_cal,
    FunctionCmdCode2st_help_boot,
    FunctionCmdCode2st_help_protection,
    FunctionCmdCode2st_help_SystemId_RL,
    FunctionCmdCode2st_help_rs485_addr,
    FunctionCmdCode2st_help_version,
    FunctionCmdCode2st_help_control_loop,
    FunctionCmdCode2st_help_emergency_pin_mode,
};

enum FunctionCmdCode2st_reboot_Enum
{
    FunctionCmdCode2st_reboot_null = 0,
};

enum FunctionCmdCode2st_encoder_calibrate_Enum
{
    FunctionCmdCode2st_encoder_calibrate_null = 0,
};

enum FunctionCmdCode2st_encoder_calibrate_official_Enum
{
    FunctionCmdCode2st_encoder_calibrate_official_null = 0,
};

enum FunctionCmdCode2st_elec_offset_calibrate_Enum
{
    FunctionCmdCode2st_elec_offset_calibrate_null = 0,
};

enum FunctionCmdCode2st_control_Enum
{
    FunctionCmdCode2st_control_null = 0,
    FunctionCmdCode2st_control_en_0,
    FunctionCmdCode2st_control_en_1,
    FunctionCmdCode2st_control_toggle,
    FunctionCmdCode2st_control_status,
};

enum FunctionCmdCode2st_sys_param_Enum
{
    FunctionCmdCode2st_sys_param_null = 0,
    FunctionCmdCode2st_sys_param_write,
    FunctionCmdCode2st_sys_param_read,
    FunctionCmdCode2st_sys_param_update,
};

enum FunctionCmdCode2st_flash_param_Enum
{
    FunctionCmdCode2st_flash_param_null = 0,
    FunctionCmdCode2st_flash_param_reset,
    FunctionCmdCode2st_flash_param_check,
    FunctionCmdCode2st_flash_param_save,
    FunctionCmdCode2st_flash_param_load,
    FunctionCmdCode2st_flash_param_write,
    FunctionCmdCode2st_flash_param_read,
};

enum FunctionCmdCode2st_get_Enum
{
    FunctionCmdCode2st_get_null = 0,
    FunctionCmdCode2st_get_pos_ref,
    FunctionCmdCode2st_get_spd_ref,
    FunctionCmdCode2st_get_id_ref,
    FunctionCmdCode2st_get_iq_ref,
    FunctionCmdCode2st_get_pos_fdb,
    FunctionCmdCode2st_get_spd_fdb,
    FunctionCmdCode2st_get_id_fdb,
    FunctionCmdCode2st_get_iq_fdb,
    FunctionCmdCode2st_get_ia_fdb,
    FunctionCmdCode2st_get_ib_fdb,
    FunctionCmdCode2st_get_steps,
    FunctionCmdCode2st_get_dir,
    FunctionCmdCode2st_get_en,
    FunctionCmdCode2st_get_stall_is_trigger,
    FunctionCmdCode2st_get_encoder_fdb_singleturn,
    FunctionCmdCode2st_get_encoder_fdb_multiturn,
    FunctionCmdCode2st_get_board_temp,
    FunctionCmdCode2st_get_board_power,
};

enum FunctionCmdCode2st_logger_Enum
{
    FunctionCmdCode2st_logger_null = 0,
    FunctionCmdCode2st_logger_en_0,
    FunctionCmdCode2st_logger_en_1,
    FunctionCmdCode2st_logger_continuous_mode_0,
    FunctionCmdCode2st_logger_continuous_mode_1,
    FunctionCmdCode2st_logger_trigger_0,
    FunctionCmdCode2st_logger_trigger_1,
};

enum FunctionCmdCode2st_boot_Enum
{
    FunctionCmdCode2st_boot_null = 0,
};

enum FunctionCmdCode2st_protection_Enum
{
    FunctionCmdCode2st_protection_null = 0,
    FunctionCmdCode2st_protection_en_0,
    FunctionCmdCode2st_protection_en_1,
    FunctionCmdCode2st_protection_report_0,
    FunctionCmdCode2st_protection_report_1,
    FunctionCmdCode2st_protection_reset,
    FunctionCmdCode2st_protection_err_code_backup,
    FunctionCmdCode2st_protection_err_code,
    FunctionCmdCode2st_protection_warning_code_backup,
    FunctionCmdCode2st_protection_warning_code,
    FunctionCmdCode2st_protection_all_code_backup,
    FunctionCmdCode2st_protection_all_code,
};

enum FunctionCmdCode2st_systemid_Enum
{
    FunctionCmdCode2st_systemid_RL_null = 0,
    FunctionCmdCode2st_systemid_RL_A,
    FunctionCmdCode2st_systemid_RL_B,
    FunctionCmdCode2st_systemid_RL_ALL_NoSaving,
    FunctionCmdCode2st_systemid_RL_ALL_Saving,
};

enum FunctionCmdCode2st_rs485_addr_Enum
{
    FunctionCmdCode2st_rs485_addr_null = 0,
    FunctionCmdCode2st_rs485_addr_set = 1,
    FunctionCmdCode2st_rs485_addr_get = 2,
};

enum FunctionCmdCode1st_version_Enum
{
    FunctionCmdCode2st_version_null = 0,
    FunctionCmdCode2st_version_fireware,
    FunctionCmdCode2st_version_cmd_system,
    FunctionCmdCode2st_version_protection,
    FunctionCmdCode2st_version_flash_param,
    FunctionCmdCode2st_version_logger,
};

enum FunctionCmdCode2st_control_loop_Enum
{
    FunctionCmdCode2st_control_loop_null = 0,
    FunctionCmdCode2st_control_loop_mode_elec_angle_free,
    FunctionCmdCode2st_control_loop_mode_uduqloop,
    FunctionCmdCode2st_control_loop_mode_curloop,
    FunctionCmdCode2st_control_loop_mode_spdloop,
    FunctionCmdCode2st_control_loop_mode_posloop,
    FunctionCmdCode2st_control_loop_set_elecangle,
    FunctionCmdCode2st_control_loop_set_uduq,
    FunctionCmdCode2st_control_loop_set_idiqref,
    FunctionCmdCode2st_control_loop_set_spdref,
    FunctionCmdCode2st_control_loop_set_posref,
};

enum FunctionCmdCode2st_emergency_pin_mode_Enum
{
    FunctionCmdCode2st_emergency_pin_mode_null = 0,
    FunctionCmdCode2st_emergency_pin_mode_stall,
    FunctionCmdCode2st_emergency_pin_mode_protection,
    FunctionCmdCode2st_emergency_pin_mode_cutter_stall,
    FunctionCmdCode2st_emergency_pin_mode_get,
};

typedef struct CommunicationInterface
{
    /* public data */
    struct
    {
        union
        {
            uint16_t all;
            struct
            {
                uint8_t minor;
                uint8_t major;
            } byte;
        } number;
        char *release_date;
    } param_version;

    uint16_t param_char_cmd_support;
    uint16_t param_slave_addr;
    uint8 param_data_frame_head_master;
    uint8 param_data_frame_head_slave;
    int8 *param_receive_buff_addr;
    float32 period_s;
    DataRaw receive_data_pack;
    DataRaw send_data_pack;

    uint8 is_hex_frame;
    uint8 receive_count;
    uint8 send_count;
    uint8 args_num;
    uint8 receive_one_pack_ok;
    char cmd_and_arg[COMMAND_MAX_NUM][COMMAND_MAX_STRLEN];

    uint8_t frame_process;
    struct DataInfo
    {
        uint8_t addr;
        uint8_t frame_length;
        uint8_t status;
        uint8_t function_code;
        uint8_t *data;
        uint8_t parity_received;

        uint8_t data_len;
        uint8_t parity_cal;
        uint8_t parity_send;
    } data_info;

    uint8_t send_data_array[SNED_DATA_ARRAY_MAX_SIZE];
    uint16_t send_data_array_len;

    /* private data */

    /* public method */
    uint8 (*Init)(struct CommunicationInterface *self);
    void (*ReceiveDataPack)(struct CommunicationInterface *self, uint8 receive_byte);
    uint8 (*DataVerify)(DataRaw *data_pack);
    uint8 (*GetCommandArguments)(uint8 args_str_len, uint8 *args_str, uint8 *args_list);
    void (*CheckPassPrint)(uint8 value, uint8_t print_en, char *pass_str, char *fail_str);
    void (*CommandParsing)(int argc, char const *argv[]);
    void (*AddDataIntoSendArray)(struct CommunicationInterface *self, uint8_t data);
    void (*AddArrayIntoSendArray)(struct CommunicationInterface *self, uint8_t *data, uint16_t len);

    /* private method */

} CommunicationInterface;

/* Variable Declare ***********************************************************/

/* Function Declare ***********************************************************/
uint8 CommunicationInterface_Init(struct CommunicationInterface *self);
void CommunicationInterface_ReceiveDataPack(struct CommunicationInterface *self, uint8 receive_byte);
uint8 CommunicationInterface_DataVerify(DataRaw *data_pack);
uint8 CommunicationInterface_GetCommandArguments(uint8 args_str_len, uint8 *args_str, uint8 *args_list);
void CommunicationInterface_CheckPassPrint(uint8 value, uint8_t print_en, char *pass_str, char *fail_str);
void CommunicationInterface_CommandParsing(int argc, char const *argv[]);
void CommunicationInterface_AddDataIntoSendArray(struct CommunicationInterface *self, uint8_t data);
void CommunicationInterface_AddArrayIntoSendArray(struct CommunicationInterface *self, uint8_t *data, uint16_t len);
void CommunicationInterface_CommandParsing(int argc, char const *argv[]);
#endif